#include "timer.h"

namespace rr {
namespace nio {

CTimer::CTimer(EventLoop::Var loop)
: loop_(loop)
{
}

CTimer::~CTimer()
{

}

int32_t CTimer::Start(int32_t timer_ms)
{
    uv_timer_.data = this;
    int32_t ret = uv_timer_init(loop_->GetLoop(), &uv_timer_);
    if(0 != ret ) {
        printf("uv_timer_init error ret=%d err:%s\n", ret, uv_strerror(ret));
        return -1;
    }

    ret = uv_timer_start(&uv_timer_, CTimer::OnTimer, timer_ms, 0);
    if(0 != ret ) {
        printf("uv_timer_start error ret=%d err:%s\n", ret, uv_strerror(ret));
        return -1;
    }

    EventRecord::Sptr record = std::make_shared<EventRecord>(EventRecord::TIMER, &uv_timer_);
    loop_->GetEventRecorder()->AddRecord(record);

    return 0;
}

void CTimer::Close(const CloseCompleteCallback& cb)
{
    close_cb_ = cb;

    uv_timer_stop(&uv_timer_);

    if (uv_is_closing((uv_handle_t*)&uv_timer_) == 0) {
        uv_close((uv_handle_t*)&uv_timer_, CTimer::OnClose);
    } else {
        HandleCloseComplete();
    }
}

void CTimer::OnTimer(uv_timer_t* handle)
{
    CTimer* timer = static_cast<CTimer*>(handle->data);
    if(timer) {
        if(timer->cb_) {
            timer->cb_();
        }
    }

    return;
}

void CTimer::OnClose(uv_handle_t* handle)
{
    auto ptr = static_cast<CTimer*>(handle->data);
    ptr->loop_->GetEventRecorder()->RemoveRecord(handle);
    if(ptr) {
        ptr->HandleCloseComplete();
    }
}

void CTimer::HandleCloseComplete()
{
    if(close_cb_) {
        close_cb_();
    }
}

} //namespace 
} //namespace 
